package org.example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfig;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigBuilder;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.state.State;

import java.util.EnumSet;

/**
 * @author junjie.yang
 * @date 2023/12/26
 */
@Configuration
@EnableStateMachine
public class OrderStatusMachineConfig extends StateMachineConfigurerAdapter<OrderStatusEnum,OrderStatusChangeEventEnum> {

    @Override
    public void configure(StateMachineConfigurationConfigurer<OrderStatusEnum, OrderStatusChangeEventEnum> config) throws Exception {
        config.withConfiguration().autoStartup(true)
                .listener(listener());
    }

    @Override
    public void configure(StateMachineStateConfigurer<OrderStatusEnum, OrderStatusChangeEventEnum> states) throws Exception {
        states.withStates()
                .initial(OrderStatusEnum.WAIT_PAYMENT)
                .end(OrderStatusEnum.FINISH)
                .states(EnumSet.allOf(OrderStatusEnum.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatusEnum, OrderStatusChangeEventEnum> transitions) throws Exception {
        transitions.withExternal().source(OrderStatusEnum.WAIT_PAYMENT).target(OrderStatusEnum.WAIT_DELIVER)
                .event(OrderStatusChangeEventEnum.PAYED)
                .and()
                .withExternal().source(OrderStatusEnum.WAIT_DELIVER).target(OrderStatusEnum.WAIT_RECEIVE)
                .event(OrderStatusChangeEventEnum.DELIVERY)
                .and()
                .withExternal().source(OrderStatusEnum.WAIT_RECEIVE).target(OrderStatusEnum.FINISH)
                .event(OrderStatusChangeEventEnum.RECEIVED);
    }

    @Bean
    public StateMachineListener<OrderStatusEnum, OrderStatusChangeEventEnum> listener() {
        return new StateMachineListenerAdapter<OrderStatusEnum, OrderStatusChangeEventEnum>() {
            @Override
            public void stateChanged(State<OrderStatusEnum, OrderStatusChangeEventEnum> from, State<OrderStatusEnum, OrderStatusChangeEventEnum> to) {

                System.out.println("State change to " + to.getId());
            }
        };
    }
}
